#include "qbaiduaiio.h"

QBaiduAIIO::QBaiduAIIO(QObject *parent)
    : QObject{parent}
{
    QJsonConfig config;
    m_sClientId = config.GetId();
    m_sClientSecret = config.GetSecret();
    m_sAccessToken = GetAccessToken();
}

int QBaiduAIIO::Ask(const QString& sAsk,QString& sResponse)
{
    QNetworkRequest request;
    //header
    request.setHeader(QNetworkRequest::ContentTypeHeader, "Accept: application/json");

    //url
    request.setUrl(QUrl("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=" + m_sAccessToken));

    //ssl
    QSslConfiguration sslConf;
    sslConf.setProtocol(QSsl::TlsV1_2);
    sslConf.setPeerVerifyMode(QSslSocket::VerifyNone);
    request.setSslConfiguration(sslConf);

    // post data
    QNetworkAccessManager manager;
    m_cMessage.AddUserContent(sAsk);
    QNetworkReply *reply = manager.post(request, m_cMessage.GetJsonStr());

    // waite reply
    QEventLoop eventLoop;
    QTimer timer;
    timer.setInterval(5000);    // set 5s timeout
    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout, &eventLoop, &QEventLoop::quit);
    connect(&manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
    timer.start();
    eventLoop.exec();

    if(timer.isActive()) {
        timer.stop();
    } else {
        disconnect(&manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
        reply->abort();
        qDebug() << "https request timeout";
        return 0;
    }

    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    if(reply->error() != QNetworkReply::NoError) {
        reply->deleteLater();
        return statusCode;
    } else {
        statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        // server reply normal
        if(statusCode == 200) {
            sResponse = GetResponse(reply->readAll());
            m_cMessage.AddAssistantContent(sResponse);
        } else {
            reply->deleteLater();
            return statusCode;
        }
    }
    return statusCode;
}

QString QBaiduAIIO::GetAccessToken()
{
    QString sToken;
    QNetworkRequest request;
    //header
    request.setHeader(QNetworkRequest::ContentTypeHeader, "Content-Type: application/x-www-form-urlencoded");
    request.setHeader(QNetworkRequest::ContentTypeHeader, "Accept: application/json");

    //url
    request.setUrl(QUrl("https://aip.baidubce.com/oauth/2.0/token"));

    //data
    QString sData = "grant_type=client_credentials&client_id=" + m_sClientId + "&client_secret=" + m_sClientSecret;
    QByteArray data = sData.toUtf8();
    //ssl
    QSslConfiguration sslConf;
    sslConf.setProtocol(QSsl::TlsV1_2);
    sslConf.setPeerVerifyMode(QSslSocket::VerifyNone);
    request.setSslConfiguration(sslConf);

    // post
    QNetworkAccessManager manager;;
    QNetworkReply *reply = manager.post(request, data);

    // waite reply
    QEventLoop eventLoop;
    QTimer timer;
    timer.setInterval(5000);    // set 5s timeout
    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout, &eventLoop, &QEventLoop::quit);
    connect(&manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
    timer.start();
    eventLoop.exec();

    if(timer.isActive()) {
        timer.stop();
    } else {
        disconnect(&manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
        reply->abort();
        qDebug() << "https request timeout";
        return 0;
    }

    if(reply->error() != QNetworkReply::NoError) {
        reply->deleteLater();
        return sToken;
    } else {
        int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        // server reply normal
        if(statusCode == 200) {
            QByteArray replyContent = reply->readAll();
            QJsonDocument loadDoc(QJsonDocument::fromJson(replyContent));
            QJsonObject object = loadDoc.object();
            sToken = object["access_token"].toString();
        } else {
            reply->deleteLater();
            return sToken;
        }
    }
    return sToken;
}

QString QBaiduAIIO::GetResponse(const QByteArray& json)
{
    QJsonDocument loadDoc(QJsonDocument::fromJson(json));
    QJsonObject object = loadDoc.object();
    QString sRes = object["result"].toString();
    return sRes.isEmpty() ? QString(json) : sRes;
}
